#include "yingceservice.h"
#include "libs/core/model/attention.h"
#include "libs/core/model/presenter.h"
#include "libs/core/model/recordinfo.h"
#include "libs/core/user/userdetail.h"
#include "serverliveinfo.h"
#include "usersettings.h"
#include <QJsonDocument>
#include <QJsonObject>

YingCeService* YingCeService::instance_ = nullptr;

YingCeService::YingCeService(QObject* parent) : yc::Service(parent)
{
    instance_ = this;
}

YingCeService::~YingCeService()
{
    instance_ = nullptr;
}

void YingCeService::setAuthentication(const QString& access_token, const QString& refresh_token)
{
    Q_UNUSED(refresh_token)
    headers().insert("Authorization", access_token);
}

int YingCeService::registerUser(const QString& name, const QString& password,
                                const QString& auth_code, const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString url = UserSettings::instance().serviceUrls().users + "/register";
    const QJsonObject jo { { "name", name }, { "password", password }, { "authCode", auth_code } };
    const QString body = QJsonDocument(jo).toJson(QJsonDocument::Compact);
    const yc::Request request(seq, url, body);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::loginByName(const QString& name, const QString& password,
                               const QString& auth_code, const QString& device,
                               const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString url = UserSettings::instance().serviceUrls().auth + "/loginByName";
    const QJsonObject jo {
        { "name", name }, { "password", password }, { "authCode", auth_code }, { "device", device }
    };
    const QString body = QJsonDocument(jo).toJson(QJsonDocument::Compact);
    const yc::Request request(seq, url, body);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::loginByToken(const QString& name, const QString& access_token,
                                const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString url = UserSettings::instance().serviceUrls().auth + "/loginByToken";
    const QJsonObject jo { { "name", name }, { "accessToken", access_token } };
    const QString body = QJsonDocument(jo).toJson(QJsonDocument::Compact);
    const yc::Request request(seq, url, body);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::refreshToken(const QString& refresh_token, const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString full_url = UserSettings::instance().serviceUrls().auth + "/accessToken";
    const yc::Request request(seq, full_url, refresh_token);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::logout(const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString url = UserSettings::instance().serviceUrls().auth + "/logout";
    const yc::Request request(seq, url, QString());
    sendRequest(request, handler);
    return seq;
}

int YingCeService::changeUser(const yc::UserDetail& detail, const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString url = UserSettings::instance().serviceUrls().users;
    const QJsonObject jo { { "nickname", detail.nickname() },
                           { "gender", detail.gender() },
                           { "profile", detail.profile() } };
    const QString body = QJsonDocument(jo).toJson(QJsonDocument::Compact);
    const yc::Request request(seq, url, body, yc::Request::PUT_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::changeUserCover(const QString& cover, const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QJsonObject jo { { "cover", cover } };
    const QString body = QJsonDocument(jo).toJson(QJsonDocument::Compact);
    const yc::Request request(seq, UserSettings::instance().serviceUrls().users, body,
                              yc::Request::PUT_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::changeUserAvatar(const QString& avatar, const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QJsonObject jo { { "avatar", avatar } };
    const QString body = QJsonDocument(jo).toJson(QJsonDocument::Compact);
    const yc::Request request(seq, UserSettings::instance().serviceUrls().users, body,
                              yc::Request::PUT_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::changePassword(const QString& password, const QString& new_password,
                                  const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString url = UserSettings::instance().serviceUrls().users + "/password";
    const QJsonObject jo { { "password", password }, { "newPassword", new_password } };
    const QString body = QJsonDocument(jo).toJson(QJsonDocument::Compact);
    const yc::Request request(seq, url, body, yc::Request::PUT_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::deleteUser(int id, const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString url = UserSettings::instance().serviceUrls().auth + QString("/%1").arg(id);
    const yc::Request request(seq, url, QString(), yc::Request::DELETE_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::getAllPlatforms(const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const yc::Request request(seq, UserSettings::instance().serviceUrls().platforms, QString(),
                              yc::Request::GET_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::getLiveWebEntry(int platform, const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString url =
            UserSettings::instance().serviceUrls().platforms + QString("/%1").arg(platform);
    const yc::Request request(seq, url, QString(), yc::Request::GET_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::searchPresenters(int platform, const QString& keyword, int start_index,
                                    const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString url = UserSettings::instance().serviceUrls().presenters
            + QString("/search?platform=%1&keyword=%2&startIndex=%3")
                      .arg(platform)
                      .arg(keyword)
                      .arg(start_index);
    const yc::Request request(seq, url, QString(), yc::Request::GET_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::getPresenters(const QList<int>& ids, const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    QJsonArray ja;
    for (int id : ids) {
        ja.push_back(id);
    }
    const QString body = QJsonDocument(ja).toJson(QJsonDocument::Compact);
    const QString url = UserSettings::instance().serviceUrls().presenters;
    const yc::Request request(seq, url, body, yc::Request::GET_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::getPresenter(int id, const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString url = UserSettings::instance().serviceUrls().presenters + QString("/%1").arg(id);
    const yc::Request request(seq, url, QString(), yc::Request::GET_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::getPresenters(int platform, const QStringList& platform_ids,
                                 const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QJsonObject jo { { "platform", platform },
                           { "platformIds", QJsonArray::fromStringList(platform_ids) } };
    const QString body = QJsonDocument(jo).toJson(QJsonDocument::Compact);
    const QString url =
            UserSettings::instance().serviceUrls().presenters + QString("/getByPlatformIds");
    const yc::Request request(seq, url, body, yc::Request::GET_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::addPresenter(const yc::Presenter& presenter, const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString body = QJsonDocument(presenter.toJsonObject()).toJson(QJsonDocument::Compact);
    const yc::Request request(seq, UserSettings::instance().serviceUrls().presenters, body,
                              yc::Request::PUT_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::getPresenterStatus(int id, const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString url =
            UserSettings::instance().serviceUrls().presenters + QString("/status/%1").arg(id);
    const yc::Request request(seq, url, QString(), yc::Request::GET_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::updatePresenterStatus(int id, int status, int active_live, int audience_count,
                                         const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString url = UserSettings::instance().serviceUrls().presenters + QString("/%1").arg(id);
    const QJsonObject jo { { "status", status },
                           { "activeLive", active_live },
                           { "audienceCount", audience_count } };
    const QString body = QJsonDocument(jo).toJson(QJsonDocument::Compact);
    const yc::Request request(seq, url, body, yc::Request::PUT_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::getAttentions(int page_num, const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString url = UserSettings::instance().serviceUrls().attentions
            + QString("?pageNum=%1").arg(page_num);
    const yc::Request request(seq, url, QString(), yc::Request::GET_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::addAttentions(const QList<yc::Attention>& attentions,
                                 const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    QJsonArray ja;
    for (const auto& i : attentions) {
        ja.push_back(i.toJsonObject());
    }
    const QString body = QJsonDocument(ja).toJson(QJsonDocument::Compact);
    const yc::Request request(seq, UserSettings::instance().serviceUrls().attentions, body,
                              yc::Request::PUT_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::changeAttentionAutoCheck(int id, bool auto_check,
                                            const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString url = UserSettings::instance().serviceUrls().attentions + QString("/%1").arg(id);
    const QJsonObject jo { { "autoCheck", auto_check } };
    const QString body = QJsonDocument(jo).toJson(QJsonDocument::Compact);
    const yc::Request request(seq, url, body, yc::Request::PUT_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::changeAttentionAutoRecord(int id, bool auto_record,
                                             const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString url = UserSettings::instance().serviceUrls().attentions + QString("/%1").arg(id);
    const QJsonObject jo { { "autoRecord", auto_record } };
    const QString body = QJsonDocument(jo).toJson(QJsonDocument::Compact);
    const yc::Request request(seq, url, body, yc::Request::PUT_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::changeAttentionCategory(int id, int category, const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString url = UserSettings::instance().serviceUrls().attentions + QString("/%1").arg(id);
    const QJsonObject jo { { "category", category } };
    const QString body = QJsonDocument(jo).toJson(QJsonDocument::Compact);
    const yc::Request request(seq, url, body, yc::Request::PUT_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::deleteAttentions(const QList<int>& ids, const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString url = UserSettings::instance().serviceUrls().attentions;
    QJsonArray ja;
    for (int id : ids) {
        ja.push_back(id);
    }
    const QString body = QJsonDocument(ja).toJson(QJsonDocument::Compact);
    const yc::Request request(seq, url, body, yc::Request::POST_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::getLive(int id, const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString url = UserSettings::instance().serviceUrls().lives + QString("/%1").arg(id);
    const yc::Request request(seq, url, QString(), yc::Request::GET_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::addLive(const yc::LiveInfo& live_info, const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString body = QJsonDocument(ServerLiveInfo::fromLiveInfo(live_info).toJsonObject())
                                 .toJson(QJsonDocument::Compact);
    const yc::Request request(seq, UserSettings::instance().serviceUrls().lives, body,
                              yc::Request::PUT_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::getLiveByPlatformId(const QString& platform_id,
                                       const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString url = UserSettings::instance().serviceUrls().lives
            + QString("/platformIds/%1").arg(platform_id);
    const yc::Request request(seq, url, QString(), yc::Request::GET_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::getLiveStatus(int id, const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString url =
            UserSettings::instance().serviceUrls().lives + QString("/status/%1").arg(id);
    const yc::Request request(seq, url, QString(), yc::Request::GET_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::updateLiveStatus(int id, int status, int view_count, int like_count,
                                    const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString url = UserSettings::instance().serviceUrls().lives + QString("/%1").arg(id);
    const QJsonObject jo { { "status", status },
                           { "viewCount", view_count },
                           { "likeCount", like_count } };
    const QString body = QJsonDocument(jo).toJson(QJsonDocument::Compact);
    const yc::Request request(seq, url, body, yc::Request::PUT_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::getRecords(int presenter, int start_index, const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString url = UserSettings::instance().serviceUrls().records
            + QString("?presenter=%1&startIndex=%2").arg(presenter).arg(start_index);
    const yc::Request request(seq, url, QString(), yc::Request::GET_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::addRecord(const yc::RecordInfo& record, const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString body = QJsonDocument(record.toJsonObject()).toJson(QJsonDocument::Compact);
    const yc::Request request(seq, UserSettings::instance().serviceUrls().records, body,
                              yc::Request::PUT_METHOD);
    sendRequest(request, handler);
    return seq;
}

int YingCeService::deleteRecords(const QList<int>& ids, const yc::ResponseHandler& handler)
{
    const int seq = getNextSeq();
    const QString url = UserSettings::instance().serviceUrls().records;
    QJsonArray ja;
    for (int id : ids) {
        ja.push_back(id);
    }
    const QString body = QJsonDocument(ja).toJson(QJsonDocument::Compact);
    const yc::Request request(seq, url, body, yc::Request::POST_METHOD);
    sendRequest(request, handler);
    return seq;
}
